#! /usr/bin/env python
"""
::BOH
$Id: monitor.py,v 1.3 2006/04/19 01:20:00

Copyright (c) 2006 George Bobeck. All rights reserved.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
::EOH

OWTF data monitor daemon.

You must be running OWFS for this to work.
All temperatures are in degrees C.
"""
import pickle
import sys, os 
import ow
from reading import *
from socket import *
from time import *
from datetime import *

def conf(location):
    f = open(location,'r')
    a = f.readlines()
    fl = []
    var_list = []
    for e in a:
        if "#" not in e:
            e = e.strip('\n')
            e = e.strip('\r')
            if e == '':
                pass
            else:
                e = e.split("\t")
                try:
                    e.remove('')
                except:
                    pass
            var_list.extend(e)
    return var_list

confs = conf(sys.argv[ 1 ])

# Notes on host:
# "224.0.0.1" = MULTICAST address, send to all on subnet
# "" = localhost
# "<address>" = sends to that address.  
verbose = bool(confs[confs.index("verbose")+1])
host = confs[confs.index("host")+1]
port = int(confs[confs.index("port")+1])
buf = 1024
addr = ( host,port )
UDPSock = socket( AF_INET,SOCK_DGRAM ) # Create UDP Socket
ID = confs[confs.index("ID")+1]
OWsource = confs[confs.index("OWsource")+1]
sensors_conf = confs[confs.index("sensors_conf")+1]
resolution = int(confs[confs.index("resolution")+1])
if verbose:
    print "Verbose Mode Enabled"
    print "host: ",host
    print "port: ", port
    print "Monitor ID: ",ID
    print "OWFS source: ",OWsource
    print "Sensors.conf at: ",sensors_conf
    print "Resolution (in senconds): ",resolution
#host = '224.0.0.1'
#port = 50000
#ID = "Monitor 1"
#OWsource = "/dev/ttyS0"
#sensors_conf = '/code/weather/owtf/sensors.conf'
#resolution = 300 #number of SECONDS, for sleep()

# This version of monitor is limited to the following Chips / Family codes:
# "DS1920":10,"DS18S20":10,"DS1921":21,"DS1822":22,"DS2438":26,"DS2436":1B
types = ( "DS1920","DS18S20","DS1921","DS1822","DS2438","DS2436" )
ad = {}

def monitor( ):
    global ad
    root = ow.Sensor( '/' )
    for sensor in root.find( all=True ):
        st = sensor._type
        if st in types:
            a = reading()
            tm = datetime.today()
            tm = tm.strftime( "%Y-%m-%d %H:%M:%S" ) # YYYY-MM-DD HH:MM:SS  
            ct = float( sensor.temperature )
            a.SetMID( ID )
            a.SetSID( sensor.address)
            a.SetLocation( ad[str(sensor.address)])
            a.SetTime( tm )
            a.SetTemp( ct )
            # Change in future version, make fully functional
            try:
                if sensor.humidity < 100 and sensor.humidity > 0.0:
                    a.SetHumid( sensor.humidity)
                else:
                    a.SetHumid(0.0)
            except:
                a.SetHumid( 0.0 )
            # Unused at this point.  For Future Feature Expansion
            a.SetV1(0.0)
            a.SetV2(0.0)
            # ---
            data2 = pickle.dumps( a )
            UDPSock.sendto( data2,addr )
        else:
            print >>sys.stderr, "OOPS: Sensor Not Supported!!"

def sensconf():
    
    f = open(sensors_conf,'r')
    sl = f.readlines()
    global ad
    ad = {}
    for s in sl:
        if "#" not in s:
            s = s.strip('\n')
            s2 = s.split('\t')
            if len(s2) == 2:
                ad[s2[0]] = s2[1]
            else:
                pass
        else:
            pass

def main():
    sensconf()
    while 1:
        ow.init( OWsource )
        monitor( )
        sleep( resolution )

if __name__ == "__main__":
    try: 
        pid = os.fork() 
        if pid > 0:
            # exit first parent
            sys.exit(0) 
    except OSError, e: 
        print >>sys.stderr, "ERROR: fork #1 failed: %d (%s)" % (e.errno, e.strerror) 
        sys.exit(1)

    # decouple from parent environment
    os.chdir("/") 
    os.setsid() 
    os.umask(0) 

    # do second fork
    try: 
        pid = os.fork() 
        if pid > 0:
            # exit from second parent, print eventual PID before
            if verbose:
                print "Monitor PID %d" % pid 
            sys.exit(0) 
    except OSError, e: 
        print >>sys.stderr, "ERROR: fork #2 failed: %d (%s)" % (e.errno, e.strerror) 
        sys.exit(1) 

    # start the daemon main loop
    main() 
